package com.brotherly.framework.transaction;

import java.util.HashMap;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;

import com.brotherly.framework.event.EventService;
import com.brotherly.framework.http.HttpService;
import com.brotherly.framework.http.NetworkWatcher;
import com.brotherly.framework.log.LogService;
import com.brotherly.framework.service.IService;
import com.brotherly.framework.service.ServiceHost;
import com.brotherly.framework.service.ServiceManager;
import com.brotherly.framework.storage.SimpleStorageService;
import com.brotherly.framework.timer.TimerService;
import com.brotherly.mpgp.remoteinterface.RemoteServerService;

public class TransactionServiceHost extends ServiceHost
{
    protected static TransactionServiceHost instance;

    protected static ThreadPoolExecutor threadPool;

    public static TransactionServiceHost getInstance()
    {
        return instance;
    }

    public static ThreadPoolExecutor getThreadPool()
    {
        return threadPool;
    }

    public static void initThreadPool(Context context)
    {
        SharedPreferences preferences = context
                .getSharedPreferences("com.brotherly.framework.transaction", Context.MODE_PRIVATE);

        int size = preferences.getInt("threadpool.size", 0);
        int maxsize = preferences.getInt("threadpool.maxsize", 5);
        int waitsize = preferences.getInt("threadpool.waitsize", 300);
        long alive = preferences.getInt("threadpool.alive_time", 1000);
        int policy = preferences.getInt("threadpool.policy", 3);

        ArrayBlockingQueue<Runnable> deques = new ArrayBlockingQueue<Runnable>(waitsize);
        RejectedExecutionHandler handler = null;

        switch (policy)
        {
            case 0:
                handler = new ThreadPoolExecutor.AbortPolicy();
                break;

            case 1:
                handler = new ThreadPoolExecutor.CallerRunsPolicy();
                break;

            case 2:
                handler = new ThreadPoolExecutor.DiscardOldestPolicy();
                break;

            default:
            case 3:
                handler = new ThreadPoolExecutor.DiscardPolicy();
                break;
        }

        threadPool = new ThreadPoolExecutor(size, maxsize, alive, TimeUnit.MILLISECONDS, deques, handler);
    }

    private SimpleStorageService storageServ;

    public TransactionServiceHost()
    {
        instance = this;
    }

    public SimpleStorageService getStorageServ()
    {
        return storageServ;
    }

    public void initComponent() throws Exception
    {
        TransactionService transactionService = (TransactionService) iServices.get(TransactionService.description);

        transactionService.registerPacemakerFactory(LocationPacemaker.type, new LocationPacemaker(this));
        transactionService.registerPacemakerFactory(TimerPacemaker.type, new TimerPacemaker(this));

        transactionService.registerDriverFactory(HttpDriver.type, new HttpDriver());

        NetworkWatcher.getInstance().start();
    }

    @Override
    public void onCreate()
    {
        super.onCreate();
        iServices = new HashMap<String, IService>();
        iServices.put(EventService.description, new EventService(this));
        iServices.put(SimpleStorageService.description, new SimpleStorageService(this));
        iServices.put(LogService.description, new LogService());
        // iServices.put(EventService.description, new EventService(this));
        iServices.put(TransactionService.description, new TransactionService());
        iServices.put(TimerService.description, new TimerService());
        iServices.put(HttpService.description, new HttpService(this));
        iServices.put(RemoteServerService.description, new RemoteServerService());

        initThreadPool(this);

        try
        {
            initComponent();
        }
        catch (Exception e)
        {}
    }

    @Override
    public void onDestroy()
    {
        uninitComponent();
        super.onDestroy();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId)
    {
        int i = super.onStartCommand(intent, flags, startId);
        ServiceManager.getInstance().onServiceStart(this);
        return i;

    }

    public void setStorageServ(SimpleStorageService storageServ)
    {
        this.storageServ = storageServ;
    }

    public void uninitComponent()
    {}
}
